package com.sun.web.utils;

import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.junit.Test;
import org.springframework.stereotype.Component;

import sun.misc.BASE64Encoder;

import com.mysql.jdbc.util.Base64Decoder;

@Component
public class CipherUtils {

	public static SecretKey secretKey = genKeyAES();

	@Test
	public void testAES() throws Exception {
		String source = "hello*_^";

		SecretKey secretKey = genKeyAES();
		String ciphertext = encryptAES(source, secretKey);
		decryptAES(ciphertext, secretKey);

	}

	public static SecretKey genKeyAES()  {
		// 生成密钥
		try {
			KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
			keyGenerator.init(128);
			SecretKey secretKey = keyGenerator.generateKey();

			System.out.println("key:" + key2String(secretKey));
			return secretKey;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return secretKey;
	}

	public static String encryptAES(String source, SecretKey secretKey)
			throws Exception {
		byte[] ciphertext;
		// 数据加密
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.ENCRYPT_MODE, secretKey);
		ciphertext = cipher.doFinal(source.getBytes("utf-8"));
		System.out.println("ciphertext length:" + ciphertext.length);

		// System.out.println("ciphertext:" + new String(ciphertext));
		// //不能这样写，显示乱码，需要用base64编码
		System.out.println("ciphertext:"
				+ Base64.getEncoder().encodeToString(ciphertext));
		return Base64.getEncoder().encodeToString(ciphertext);
	}

	public static String decryptAES(String ciphertext, SecretKey secretKey)
			throws Exception {
		// 数据解密
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.DECRYPT_MODE, secretKey);

		byte[] plaintext = cipher.doFinal(Base64.getDecoder()
				.decode(ciphertext));

		// byte[] plaintext = cipher.doFinal(ciphertext.getBytes());
		// javax.crypto.IllegalBlockSizeException: Input length must be multiple
		// of 16 when decrypting with padded cipher

		String result = new String(plaintext, "utf-8");
		System.out.println("plaintext:" + result);

		return result;
	}

	public static String decryptAES(byte[] ciphertext, SecretKey secretKey)
			throws Exception {
		// 数据解密
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.DECRYPT_MODE, secretKey);

		byte[] plaintext = cipher.doFinal(ciphertext);

		// byte[] plaintext = cipher.doFinal(ciphertext.getBytes());
		// javax.crypto.IllegalBlockSizeException: Input length must be multiple
		// of 16 when decrypting with padded cipher

		System.out.println("plaintext:" + new String(plaintext));

		return Base64.getEncoder().encodeToString(plaintext);
	}

	public static String key2String(SecretKey secretKey) {
		return Base64.getEncoder().encodeToString(secretKey.getEncoded());
	}

	public static SecretKey string2key(String keyString) {
		// decode the base64 encoded string
		byte[] decodedKey = Base64.getDecoder().decode(keyString);
		// rebuild key using SecretKeySpec
		SecretKey originalKey = new SecretKeySpec(decodedKey, 0,
				decodedKey.length, "AES");
		return originalKey;
	}
	
	
	/**
     * 对字符串加密,加密算法使用MD5,SHA-1,SHA-256,默认使用SHA-256
     * 
     * @param strSrc
     *            要加密的字符串
     * @param encName
     *            加密类型
     * @return
     */
	
	public static String EncryptWithSha256(String strSrc) {
		return EncryptWithSha256(strSrc, null);
	}
    public static String EncryptWithSha256(String strSrc, String encName) {
        MessageDigest md = null;
        String strDes = null;

        byte[] bt = strSrc.getBytes();
        try {
            if (encName == null || encName.equals("")) {
                encName = "SHA-256";
            }
            md = MessageDigest.getInstance(encName);
            md.update(bt);
            strDes = bytes2Hex(md.digest()); // to HexString
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
        return strDes;
    }

    public static String bytes2Hex(byte[] bts) {
        String des = "";
        String tmp = null;
        for (int i = 0; i < bts.length; i++) {
            tmp = (Integer.toHexString(bts[i] & 0xFF));
            if (tmp.length() == 1) {
                des += "0";
            }
            des += tmp;
        }
        return des;
    }

}
